package org.ysh.service;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.CredentialsException;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.ysh.core.cache.Constants;
import org.ysh.core.exceptions.UserNotAllowModifyException;
import org.ysh.core.utils.PasswordUtils;
import org.ysh.core.utils.RandomUtils;
import org.ysh.core.utils.ShiroUtils;
import org.ysh.core.utils.StringUtils;
import org.ysh.domain.User;
import org.ysh.domain.UserDept;
import org.ysh.domain.UserRole;
import org.ysh.mapper.UserDeptMapper;
import org.ysh.mapper.UserMapper;
import org.ysh.mapper.UserRoleMapper;
import org.ysh.vo.UserVo;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class UserService extends BaseService<Integer, User>{

    @Resource
    private UserRoleMapper userRoleMapper;

    @Resource
    private UserDeptMapper userDeptMapper;
    @Resource
    private UserMapper userMapper;

    public UserService(UserMapper baseMapper) {
        super(baseMapper);
    }

    public User findByUsername(String username){
        return ((UserMapper)baseMapper).findByUsername(username);
    }

    /**
     * 更新用户密码
     * @param oldPassword
     * @param newPassword
     */
    public void updatePassword(String oldPassword,String newPassword){
        User user = (User)SecurityUtils.getSubject().getSession().getAttribute(Constants.CURRENT_USER);
        //校验旧密码是否正确
        SimpleHash hash = new SimpleHash("MD5", oldPassword, user.getSalt().toCharArray(),2);
        String password = hash.toHex();
        if(!password.equals(user.getPassword())){
          throw new CredentialsException("旧密码输入错误");
        }
        //更新密码
        hash = new SimpleHash("MD5", newPassword, user.getSalt().toCharArray(),2);
        password = hash.toHex();
        user.setPassword(password);
        update(user);
    }

    /**
     * 批量保存用户
     * @param users
     */
    public void batchSave(List<User> users){
        users.forEach(user -> {
            user.setCreateTime(new Date());
            user.setSalt(RandomUtils.generateShortUuid(8));
            insert(user);
        });
    }

    /**
     * 保存用户信息和权限信息
     * @param user
     */
    public void saveUserWithRoleIds(User user){
        user.setCreateTime(new Date());
        user.setSalt(RandomUtils.generateShortUuid(8));
        user.setPassword(PasswordUtils.encryptPassword(user.getPassword(), user.getSalt()));
        userMapper.insert(user);
        // 设置用户权限
        saveUserRole(user);
        //设置用户部门
        saveUserDept(user);
    }

    private void saveUserRole(Integer userId,Integer roleId){
        UserRole userRole = new UserRole();
        userRole.setUserId(userId);
        userRole.setRoleId(roleId);
        userRole.setCreateTime(new Date());
        userRoleMapper.insert(userRole);
    }

    private void saveUserDept(Integer userId,Integer deptId){
        UserDept userDept = new UserDept();
        userDept.setUserId(userId);
        userDept.setDeptId(deptId);
        userDept.setCreateTime(new Date());
        userDeptMapper.insert(userDept);
    }

    private void saveUserRole(User user){
        String roleIds = user.getRoleIds();
        if(StringUtils.isNotEmpty(roleIds)){
            if(roleIds.contains(",")){
                String[] roleIdArr  = roleIds.split(",");
                for (String s : roleIdArr) {
                    saveUserRole(user.getId(),Integer.parseInt(s));
                }
            }else{
                saveUserRole(user.getId(),Integer.parseInt(roleIds));
            }
        }
    }

    private void saveUserDept(User user){
        String deptIds = user.getDeptIds();
        if(StringUtils.isNotEmpty(deptIds)){
            if(deptIds.contains(",")){
                String[] roleIdArr  = deptIds.split(",");
                for (String s : roleIdArr) {
                    saveUserDept(user.getId(),Integer.parseInt(s));
                }
            }else{
                saveUserDept(user.getId(),Integer.parseInt(deptIds));
            }
        }
    }

    /**
     * 更新用户信息和权限信息
     * @param user
     */
    public void updateUserWithRoleIds(User user){
        if("admin".equals(user.getUsername())){
            throw new UserNotAllowModifyException(user.getUsername());
        }
        user.setUpdateTime(new Date());
        user.setUpdateBy(ShiroUtils.getCurrentUserId());
        update(user);
        //更新权限
        //删除userRoleList
        userRoleMapper.deleteUserRoleByUser(user.getId());

        saveUserRole(user);

        //删除userDeptList
        userDeptMapper.deleteUserDeptByUser(user.getId());

        //保存userDeptList
        saveUserDept(user);

    }

    /**
     * 获取用户信息和权限信息
     * @param userId
     * @return
     */
    public User findUserWithRoleIds(Integer userId){
        User user = findById(userId);
        UserRole userRole = new UserRole();
        userRole.setUserId(userId);
        List<UserRole> userRoles = userRoleMapper.findByPage(userRole);
        StringBuilder roleIds = new StringBuilder();
        for (UserRole role : userRoles) {
            roleIds.append(role.getRoleId()).append(",");
        }
        if (roleIds.length() > 0) {
            roleIds.deleteCharAt(roleIds.length() - 1);
        }
        user.setRoleIds(roleIds.toString());
        return user;

    }

    /**
     * 初始化用户密码
     * @param userId
     * @param password
     */
    public void initUserPassword(Integer userId,String password) {
        User user = findById(userId);
        if("admin".equals(user.getUsername())){
            throw new UserNotAllowModifyException(user.getUsername());
        }
        user.setPassword(PasswordUtils.encryptPassword(password, user.getSalt()));
        user.setUpdateTime(new Date());
        user.setUpdateBy(ShiroUtils.getCurrentUserId());
        update(user);
    }

    public List<UserVo> toUserVos(List<User> users) {
        return users.stream().map(user -> {
            UserVo userVo = new UserVo(user);
            List<String> roles = userRoleMapper.findRoleNamesByUserId(user.getId());
            userVo.setRoles(String.join(",", roles));
            List<String> depts = userDeptMapper.findDeptNamesByUserId(user.getId());
            userVo.setDepts(String.join(",", depts));
            return userVo;
        }).collect(Collectors.toList());
    }
}
